package com.ming.service.impl;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.ming.exception.EmpException;
import com.ming.exception.ParameterException;
import com.ming.exception.UserException;
import com.ming.mapper.EmpExprMapper;
import com.ming.mapper.EmpMapper;
import com.ming.pojo.entity.Emp;
import com.ming.pojo.entity.EmpExpr;
import com.ming.pojo.vo.EmpListVO;
import com.ming.pojo.dto.EmpQueryDTO;
import com.ming.pojo.vo.EmpVO;
import com.ming.pojo.dto.LoginDTO;
import com.ming.pojo.vo.LoginVO;
import com.ming.service.EmpService;
import com.ming.util.JwtUtils;
import com.ming.util.PasswordUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.DigestUtils;
import org.springframework.util.StringUtils;

import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.util.List;

@Slf4j
@Service
public class EmpServiceImpl implements EmpService {

    @Autowired
    private EmpMapper empMapper;

    @Autowired
    private EmpExprMapper empExprMapper;

    @Autowired
    private JwtUtils jwtUtils;

    @Override
    public List<Emp> list() {
        return empMapper.list();
    }

    @Override
    public PageInfo<EmpListVO> pageQuery(EmpQueryDTO empQueryDTO) {
        log.info("开始分页查询员工数据，页码: {}, 每页条数: {}", empQueryDTO.getPageNum(), empQueryDTO.getPageSize());

        // 设置分页参数
        PageHelper.startPage(empQueryDTO.getPageNum(), empQueryDTO.getPageSize());

        // 执行条件查询
        List<EmpListVO> empListVO = empMapper.listVOByCondition(empQueryDTO);

        // 获取分页信息
        PageInfo<EmpListVO> pageInfo = new PageInfo<>(empListVO);

        log.info("分页查询完成，总记录数: {}, 总页数: {}, 当前页记录数: {}",
                pageInfo.getTotal(), pageInfo.getPages(), pageInfo.getList().size());

        return pageInfo;
    }

    @Override
    public EmpVO getById(Integer id) {
        if (id == null || id <= 0) {
            throw EmpException.notFound("员工ID无效");
        }

        log.debug("=== 开始查询员工详情，ID = {} ===", id);

        com.ming.pojo.vo.EmpVO empVO = empMapper.getEmpVOById(id);
        if (empVO == null) {
            throw EmpException.notFound("员工不存在，ID: " + id);
        }

        log.info("找到员工：{}，ID = {}，部门：{}", empVO.getName(), empVO.getId(), empVO.getDeptName());

        log.debug("开始查询工作经历，empId = {}", id);
        List<EmpExpr> exprList = empExprMapper.getByEmpId(id);
        log.debug("查询到工作经历数量：{}", exprList.size());

        if (exprList != null && !exprList.isEmpty()) {
            log.debug("工作经历详情：");
            for (EmpExpr expr : exprList) {
                log.debug("  - ID: {}, 公司: {}, 职位: {}", expr.getId(), expr.getCompany(), expr.getJob());
            }
        } else {
            log.debug("没有找到工作经历数据");
        }

        empVO.setExprList(exprList);

        log.debug("=== 查询完成 ===");

        return empVO;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void add(Emp emp, List<EmpExpr> exprList) {
        log.info("开始创建员工事务，员工姓名: {}", emp.getName());

        try {
            // 加密密码
            if (emp.getPassword() != null) {
                String encryptedPassword = PasswordUtils.generateStoredPassword(emp.getPassword());
                emp.setPassword(encryptedPassword);
                log.info("新用户密码已加密存储");
            }

            emp.setCreateTime(LocalDateTime.now());
            emp.setUpdateTime(LocalDateTime.now());
            empMapper.insert(emp);

            log.info("员工基本信息创建成功，ID: {}", emp.getId());

            if (exprList != null && !exprList.isEmpty()) {
                for (EmpExpr expr : exprList) {
                    expr.setEmpId(emp.getId());
                    log.debug("设置工作经历empId: {}, 公司: {}", emp.getId(), expr.getCompany());
                }
                empExprMapper.insertBatch(exprList);
                log.info("成功创建{}条工作经历记录", exprList.size());
            }

            log.info("员工创建事务完成，员工ID: {}", emp.getId());
        } catch (Exception e) {
            log.error("创建员工失败，事务回滚，员工信息: {}", emp.getName(), e);
            throw e; // 重新抛出异常以触发事务回滚
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void update(Emp emp, List<EmpExpr> exprList) {
        log.info("开始更新员工事务，员工ID: {}", emp.getId());

        try {
            emp.setUpdateTime(LocalDateTime.now());
            empMapper.update(emp);
            log.info("员工基本信息更新成功，ID: {}", emp.getId());

            // 先删除原有的工作经历
            empExprMapper.deleteByEmpId(emp.getId());
            log.info("删除原有工作经历记录，员工ID: {}", emp.getId());

            if (exprList != null && !exprList.isEmpty()) {
                for (EmpExpr expr : exprList) {
                    expr.setEmpId(emp.getId());
                }
                empExprMapper.insertBatch(exprList);
                log.info("新增{}条工作经历记录，员工ID: {}", exprList.size(), emp.getId());
            }

            log.info("员工更新事务完成，员工ID: {}", emp.getId());
        } catch (Exception e) {
            log.error("更新员工失败，事务回滚，员工ID: {}", emp.getId(), e);
            throw e; // 重新抛出异常以触发事务回滚
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteById(Integer id) {
        log.info("开始删除员工事务，员工ID: {}", id);

        try {
            // 先删除相关的工作经历
            empExprMapper.deleteByEmpId(id);
            log.info("删除员工工作经历记录，员工ID: {}", id);

            // 再删除员工基本信息
            empMapper.deleteById(id);
            log.info("删除员工基本信息，员工ID: {}", id);

            log.info("员工删除事务完成，员工ID: {}", id);
        } catch (Exception e) {
            log.error("删除员工失败，事务回滚，员工ID: {}", id, e);
            throw e; // 重新抛出异常以触发事务回滚
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addExpr(EmpExpr empExpr) {
        log.info("开始添加工作经历事务，员工ID: {}", empExpr.getEmpId());

        try {
            // 检查empId是否存在，如果不存在则抛出异常
            if (empExpr.getEmpId() == null) {
                throw new IllegalArgumentException("员工ID不能为空");
            }

            // 验证员工是否存在
            if (empMapper.findById(empExpr.getEmpId()) == null) {
                throw new IllegalArgumentException("员工不存在，ID: " + empExpr.getEmpId());
            }

            empExprMapper.insert(empExpr);
            log.info("工作经历添加成功，ID: {}", empExpr.getId());
        } catch (Exception e) {
            log.error("添加工作经历失败，事务回滚，员工ID: {}", empExpr.getEmpId(), e);
            throw e; // 重新抛出异常以触发事务回滚
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateExpr(EmpExpr empExpr) {
        log.info("开始更新工作经历事务，ID: {}", empExpr.getId());

        try {
            empExprMapper.update(empExpr);
            log.info("工作经历更新成功，ID: {}", empExpr.getId());
        } catch (Exception e) {
            log.error("更新工作经历失败，事务回滚，ID: {}", empExpr.getId(), e);
            throw e; // 重新抛出异常以触发事务回滚
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteExprById(Integer id) {
        log.info("开始删除工作经历事务，ID: {}", id);

        try {
            empExprMapper.deleteById(id);
            log.info("工作经历删除成功，ID: {}", id);
        } catch (Exception e) {
            log.error("删除工作经历失败，事务回滚，ID: {}", id, e);
            throw e; // 重新抛出异常以触发事务回滚
        }
    }

    @Override
    public List<EmpExpr> getExprByEmpId(Integer empId) {
        return empExprMapper.getByEmpId(empId);
    }

    @Override
    public LoginVO login(LoginDTO loginDTO) {
        log.info("员工登录: {}", loginDTO.getUsername());

        // 1. 参数校验
        if (!StringUtils.hasText(loginDTO.getUsername())) {
            throw ParameterException.missing("username");
        }
        if (!StringUtils.hasText(loginDTO.getPassword())) {
            throw ParameterException.missing("password");
        }

        // 2. 根据用户名查询员工
        Emp emp = empMapper.getByUsername(loginDTO.getUsername());
        if (emp == null) {
            log.warn("用户不存在: {}", loginDTO.getUsername());
            throw UserException.loginFailed("用户名或密码错误");
        }

        log.info("找到用户: {}, ID: {}, 姓名: {}", emp.getUsername(), emp.getId(), emp.getName());
        log.debug("数据库中的密码: {}", emp.getPassword());

        // 3. 验证密码 - 支持多种格式
        String inputPassword = loginDTO.getPassword();
        String storedPassword = emp.getPassword();

        log.debug("输入的原始密码: {}", inputPassword);
        log.debug("数据库存储的密码: {}", storedPassword);

        boolean passwordValid = false;

        // 尝试新的加密格式（salt$encryptedPassword）
        String[] parsedPassword = PasswordUtils.parseStoredPassword(storedPassword);
        if (parsedPassword != null && parsedPassword.length == 2) {
            String salt = parsedPassword[0];
            String encryptedPassword = parsedPassword[1];
            passwordValid = PasswordUtils.validatePassword(inputPassword, encryptedPassword, salt);
            if (passwordValid) {
                log.info("使用盐值加密验证成功");
            }
        } else {
            // 兼容旧的验证方式（明文或简单MD5）
            passwordValid = PasswordUtils.validatePassword(inputPassword, storedPassword);
            if (passwordValid) {
                log.info("使用兼容模式验证成功");
            }
        }

        if (!passwordValid) {
            log.warn("密码验证失败 - 用户: {}", loginDTO.getUsername());
            throw UserException.passwordIncorrect("用户名或密码错误");
        }

        // 4. 生成 JWT token
        String token = jwtUtils.generateToken(emp.getId(), emp.getUsername(), emp.getName());

        // 5. 构建返回结果
        LoginVO loginVO = new LoginVO();
        loginVO.setId(emp.getId());
        loginVO.setName(emp.getName());
        loginVO.setUsername(emp.getUsername());
        loginVO.setToken(token);

        log.info("员工登录成功: {} (ID: {})", emp.getUsername(), emp.getId());
        return loginVO;
    }
}